package labox.innovation.gameserver.datatables;

import gnu.trove.TIntObjectHashMap;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.model.L2AccessLevel;

/**
 * 权限登记对象，管理了玩家的再游戏内的权利大小
 * 
 * @author FBIagent<br>
 */
public final class AccessLevels {

	private static final Logger _log = LoggerFactory.getLogger(AccessLevels.class.getName());

	/**
	 * GM的连接权限的等级<br>
	 */
	public static final int _masterAccessLevelNum = Config.MASTERACCESS_LEVEL;

	/**
	 * GM权限等级能够做的事情<br>
	 */
	public static L2AccessLevel _masterAccessLevel = new L2AccessLevel(_masterAccessLevelNum, "Master Access", Config.MASTERACCESS_NAME_COLOR, Config.MASTERACCESS_TITLE_COLOR, null, true, true, true, true, true, true, true, true);

	/**
	 * USER的连接权限的等级<br>
	 */
	public static final int _userAccessLevelNum = 0;

	/**
	 * USER权限等级能够做的事情<br>
	 */
	public static L2AccessLevel _userAccessLevel = new L2AccessLevel(_userAccessLevelNum, "User", Integer.decode("0xFFFFFF"), Integer.decode("0xFFFFFF"), null, false, false, false, true, false, true, true, true);

	/** FastMap of access levels defined in database<br> */
	private TIntObjectHashMap<L2AccessLevel> _accessLevels;

	/**
	 * Returns the one and only instance of this class<br>
	 * <br>
	 * 
	 * @return AccessLevels: the one and only instance of this class<br>
	 */
	public static AccessLevels getInstance() {
		return SingletonHolder._instance;
	}

	private AccessLevels() {
		loadAccessLevels();
	}

	/**
	 * Loads the access levels from database<br>
	 */
	private void loadAccessLevels() {
		_accessLevels = new TIntObjectHashMap<L2AccessLevel>();

		Connection con = null;

		try {
			con = L2DatabaseFactory.getInstance().getConnection();

			PreparedStatement stmt = con.prepareStatement("SELECT * FROM `access_levels` ORDER BY `accessLevel` DESC");
			ResultSet rset = stmt.executeQuery();
			int accessLevel = 0;
			String name = null;
			int nameColor = 0;
			int titleColor = 0;
			String childs = null;
			boolean isGm = false;
			boolean allowPeaceAttack = false;
			boolean allowFixedRes = false;
			boolean allowTransaction = false;
			boolean allowAltG = false;
			boolean giveDamage = false;
			boolean takeAggro = false;
			boolean gainExp = false;

			while (rset.next()) {
				accessLevel = rset.getInt("accessLevel");
				name = rset.getString("name");

				if (accessLevel == _userAccessLevelNum) {
					_log.warn("AccessLevels: Access level with name " + name + " is using reserved user access level " + _userAccessLevelNum + ". Ignoring it!");
					continue;
				} else if (accessLevel == _masterAccessLevelNum) {
					_log.warn("AccessLevels: Access level with name " + name + " is using reserved master access level " + _masterAccessLevelNum + ". Ignoring it!");
					continue;
				} else if (accessLevel < 0) {
					_log.warn("AccessLevels: Access level with name " + name + " is using banned access level state(below 0). Ignoring it!");
					continue;
				}

				try {
					nameColor = Integer.decode("0x" + rset.getString("nameColor"));
				} catch (NumberFormatException nfe) {
					try {
						nameColor = Integer.decode("0xFFFFFF");
					} catch (NumberFormatException nfe2) {

					}
				}

				try {
					titleColor = Integer.decode("0x" + rset.getString("titleColor"));

				} catch (NumberFormatException nfe) {
					try {
						titleColor = Integer.decode("0x77FFFF");
					} catch (NumberFormatException nfe2) {

					}
				}

				childs = rset.getString("childAccess");
				isGm = rset.getBoolean("isGm");
				allowPeaceAttack = rset.getBoolean("allowPeaceAttack");
				allowFixedRes = rset.getBoolean("allowFixedRes");
				allowTransaction = rset.getBoolean("allowTransaction");
				allowAltG = rset.getBoolean("allowAltg");
				giveDamage = rset.getBoolean("giveDamage");
				takeAggro = rset.getBoolean("takeAggro");
				gainExp = rset.getBoolean("gainExp");

				_accessLevels.put(accessLevel, new L2AccessLevel(accessLevel, name, nameColor, titleColor, childs.isEmpty() ? null : childs, isGm, allowPeaceAttack, allowFixedRes, allowTransaction, allowAltG, giveDamage, takeAggro, gainExp));
			}

			rset.close();
			stmt.close();
		} catch (SQLException e) {
			_log.error("AccessLevels: Error loading from database:", Config.SERVER_ID, e);
		} finally {
			try {
				con.close();
			} catch (Exception e) {

			}
		}
		_log.info("AccessLevels: Loaded " + _accessLevels.size() + " from database.");
	}

	/**
	 * 根据连接等级返回连接权限对象<br>
	 * <br>
	 * 
	 * @param accessLevelNum
	 *            as int<br>
	 * <br>
	 * 
	 * @return AccessLevel: AccessLevel instance by char access level<br>
	 */
	public L2AccessLevel getAccessLevel(int accessLevelNum) {
		L2AccessLevel accessLevel = null;
		accessLevel = _accessLevels.get(accessLevelNum);
		return accessLevel;
	}

	/**
	 * 禁止一个连接等级
	 * @param accessLevel
	 */
	public void addBanAccessLevel(int accessLevel) {
		if (accessLevel > -1) {
			return;
		}
		_accessLevels.put(accessLevel, new L2AccessLevel(accessLevel, "Banned", Integer.decode("0x000000"), Integer.decode("0x000000"), null, false, false, false, false, false, false, false, false));
	}

	public void reloadAccessLevels() {
		loadAccessLevels();
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder {
		protected static final AccessLevels _instance = new AccessLevels();
	}
}